#pragma once
#include "mutex.hpp"
#include "sem.hpp"
#include <vector>
#include <semaphore.h>
#include <iostream>

const static int DEF_CAP = 5;

template<class T>
class RingQueue
{
public:
    RingQueue(int cap = DEF_CAP)
        : _cap(cap)
        , _RQueue(cap)
        , _blankInd(0)
        , _dataInd(0)
    {}

    void pop(T* out)
    {
        _data.P();
        {
            GuardMutex(_conLock);
            *out = _RQueue[_dataInd];
            _dataInd--;
            _dataInd = _dataInd % _cap;
            std::cout << " 消费者拿到了一个数据:  " << std::endl;
        }
        _blank.V();
    }

    void push(T in)
    {
        _blank.P();
        {
            GuardMutex(_proLock);
            _RQueue[_blankInd] = in;
            _blankInd++;
            _blankInd = _blankInd % _cap;
            std::cout << " 生产了一个任务: " << std::endl;
        }
        _data.V();
    }

    ~RingQueue()
    {}
private:
    std::vector<T> _RQueue;      //环形队列
    size_t _cap;

    Sem _blank;                  //空资源
    Sem _data;                   //数据资源

    size_t _blankInd;            //生产者指向下标
    size_t _dataInd;             //消费者指向下标

    Mutex _proLock;              //生产者需要的锁
    Mutex _conLock;              //消费者需要的锁，支持多生产者多消费
};